package com.gitee.wsl.common.chart.sample.bubble

import android.graphics.Canvas
import android.graphics.Paint
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.adapter.DataSource
import com.gitee.wsl.common.chart.adapter.SelectItemChartAdapter
import com.gitee.wsl.common.chart.listener.click.PlotPointPosition
import com.gitee.wsl.common.chart.model.PlotDot
import com.gitee.wsl.common.chart.render.background.axis.line.CategoryLineAxis
import com.gitee.wsl.common.chart.render.background.axis.line.DataLineAxis
import com.gitee.wsl.common.chart.render.background.quadrant.Quadrant
import com.gitee.wsl.common.chart.render.shape.plot.renderDot
import com.gitee.wsl.common.chart.sample.bubble.adapter.BubbleChartAdapter
import com.gitee.wsl.common.chart.sample.bubble.model.BubbleData
import com.gitee.wsl.common.chart.sample.line.AbstractLineChart
import com.gitee.wsl.common.ui.draw.type.DotStyle
import com.gitee.wsl.android.ui.ext.type.drawRotateText
import com.gitee.wsl.transform.format.Format
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul


import timber.log.Timber

/**
 * @ClassName BubbleChart
 * @Description  气泡图基类
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */
class BubbleChart(val adapter:BubbleChartAdapter=BubbleChartAdapter()):AbstractLineChart(adapter),
    SelectItemChartAdapter<BubbleData> by adapter {
    //数据源
    var dataSet by DataSource(adapter)

    //分类轴的最大，最小值
     var maxValue = 0.0f
     var minValue = 0.0f

    //用于格式化标签的回调接口
     var labelFormatter: Format<String>? = null

    //指定气泡半径的最大大小
     var bubbleMaxSize = 0.0f
     var bubbleMinSize = 0.0f

    //指定最大气泡大小所表示的实际值，最大气泡大小由 BubbleMaxSize 设置。
     var bubbleScaleMax = 0.0f
     var bubbleScaleMin = 0.0f
    /**
     * 绘制点的画笔
     * @return
     */
     val pointPaint: Paint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG)
    }
    
     val plotDot: PlotDot = PlotDot()

     val borderPointPaint: Paint by lazy {
        Paint(Paint.ANTI_ALIAS_FLAG).apply {
            style = Paint.Style.STROKE
            strokeWidth = 2f
        }
    }

    //四象限类
     val plotQuadrant: Quadrant= Quadrant()


    override fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.BUBBLE
    }

     init{
        plotDot.dotStyle = DotStyle.DOT
        isAxesClosed=true
    }

     override fun categoryAxisDefaultSetting(categoryAxis: CategoryLineAxis) {
        super.categoryAxisDefaultSetting(categoryAxis)
        categoryAxis.tickMarksAlign=Paint.Align.CENTER
    }

    override fun dataAxisDefaultSetting(dataAxis: DataLineAxis) {
        super.dataAxisDefaultSetting(dataAxis)
         dataAxis.tickMarksAlign=Paint.Align.LEFT
    }

     private fun calcRadius(scale: Float, scaleTotalSize: Float, bubbleRadius: Float): Float {
        return Math.mul(bubbleRadius, Math.div(scale, scaleTotalSize))
    }

    /**
     * 绘制象限
     * @param canvas 画布
     */
    private fun drawQuadrant(canvas: Canvas,dataAxis: DataLineAxis) {
        if (!plotQuadrant.isVisible) return
        val xValue = plotQuadrant.quadrantXValue
        val yValue = plotQuadrant.quadrantYValue
        val centerX = getLnXValPosition(
            xValue, maxValue,
            minValue
        )
        val centerY = getVPValPosition(yValue,dataAxis)
        plotQuadrant.renderQuadrant(
            canvas, centerX, centerY,
            bodyViewport.left, bodyViewport.top, bodyViewport.right, bodyViewport.bottom
        )
    }


     private fun drawPoints(canvas: Canvas, bd: BubbleData, dataID: Int, dataAxis: DataLineAxis) {
        //得到标签对应的值数据集		
        val chartValues = bd.dataSet

        //画出数据集对应的线条	
        var YvaluePos = 0.0f
        var XvaluePos = 0.0f
        if (bubbleScaleMax.compareTo(bubbleScaleMin) == 0) {
            Timber.d( "没有指定用于决定气泡大小的最大最小实际数据值。")
            return
        }
        if (bubbleMaxSize.compareTo(bubbleMinSize) == 0) {
            Timber.d( "没有指定气泡本身，最大最小半径。")
            return
        }
        if (maxValue.compareTo(minValue) == -1) {
            Timber.d( "轴最大值小于最小值.")
            return
        }
        if (maxValue.compareTo(minValue) == 0) {
            Timber.d( "轴最大值与最小值相等.")
            return
        }
        //double xMM  = MathHelper.getInstance().sub(mMaxValue , mMinValue);
        val scale = bubbleScaleMax - bubbleScaleMin
        val size = bubbleMaxSize - bubbleMinSize
        val lstBubble = bd.bubble
        val bubbleSize = lstBubble.size
        var bubble = 0.0f
        var curRadius = 0.0f
        //汽泡颜色
        pointPaint.color = bd.color
        //边框颜色
        if (bd.borderColor != -1) borderPointPaint.color = bd.borderColor
        val itemAngle = bd.itemLabelRotateAngle
        val count = chartValues.size
        for (i in 0 until count) {
            val entry = chartValues[i]
            XvaluePos = getLnXValPosition(entry.x, maxValue, minValue)
            YvaluePos = getVPValPosition(entry.y,dataAxis)
            bubble = if (i >= bubbleSize) //j
            {
                continue
            } else {
                lstBubble[i] //j
            }
            curRadius = calcRadius(scale, size, bubble)
            if (curRadius.compareTo(0.0f) == 0 || curRadius.compareTo(0.0f) == -1) {
                //Log.e(TAG,"当前气泡半径小于或等于0。");        	
                continue
            }
            plotDot.dotRadius = curRadius
            canvas.renderDot(
                 plotDot, XvaluePos, YvaluePos, pointPaint
            )
            savePointRecord(
                dataID, i, XvaluePos + moveX, YvaluePos + moveY,  //childID
                XvaluePos - curRadius + moveX, YvaluePos - curRadius + moveY,
                XvaluePos + curRadius + moveX, YvaluePos + curRadius + moveY
            )
            if (bd.borderColor != -1) {
                canvas.drawCircle(XvaluePos, YvaluePos, curRadius, borderPointPaint)
            }


            //显示批注形状
            drawAnchor(anchorSet, dataID, i, canvas, XvaluePos, YvaluePos, curRadius)
            if (bd.isLabelVisible) {
                //请自行在回调函数中处理显示格式
                canvas.drawRotateText(
                    labelFormatter?.invoke("${entry.x},${entry.y}")?:"${entry.x},${entry.y}",
                    XvaluePos, YvaluePos, itemAngle,
                    bd.labelPaint
                ) //lineStopX,lineStopY
            }
        }
        adapter.isRecordSetInited = true
    }


    /**
     * 绘制图
     */
    private fun drawPlot(canvas: Canvas, dataAxis: DataLineAxis): Boolean {
        //检查是否有设置分类轴的最大最小值		
        if (maxValue == minValue && 0.0f == maxValue) {
            Timber.d( "请检查是否有设置分类轴的最大最小值。")
            return false
        }

        //绘制四象限
        drawQuadrant(canvas,dataAxis)

        //开始处 X 轴 即分类轴              	
        val size = dataSet.size
        for (i in 0 until size) {
            val bd = dataSet[i]
            drawPoints(canvas, bd, i,dataAxis)
        }
        return true
    }

    /////////////////////////////////////////////
    override fun drawClipPlot(canvas: Canvas, dataAxis: DataLineAxis, categoryAxis: CategoryLineAxis) {
        if (drawPlot(canvas,dataAxis)) {
            //画横向定制线
            if (null != customLine) {
                customLine!!.setVerticalPlot(dataAxis, bodyViewport, getAxisScreenHeight())
                customLine!!.renderVerticalCustomlinesDataAxis(canvas)
            }
        }
    }

     fun savePointRecord(
        dataID: Int, childID: Int,
        x: Float, y: Float, left: Float, top: Float, right: Float, bottom: Float
    ) {
        if(adapter.isRecordSetInited) return
        val pRecord = PlotPointPosition()
        pRecord.savePlotDataID(dataID)
        pRecord.savePlotDataChildID(childID)
        pRecord.savePlotPosition(x, y)
        pRecord.savePlotRectF(left, top, right, bottom)
        //pRecord.extPointClickRange(clickRangeExtValue)
        adapter.addRecordItem(pRecord)
    }


     override fun drawClipLegend(canvas: Canvas) {
       // plotLegend.renderBubbleKey(canvas, mDataset)
    }
    /////////////////////////////////////////////
}